#!BPY
# for windows place script file in
# C:\Users\Username\AppData\Roaming\Blender Foundation\Blender\2.56\scripts\addons
import bpy
import os
import struct

optimize = 1
debug    = 1

bl_addon_info = {
    "name": "EAT: Erik, Alan and Torbjoern 3D format (.eat)",
    "author": "Alan Whitburn Haugen",
    "version": (0,1),
    "blender": (2, 5, 6),
    "api": 31847,
    "location": "File > Export",
    "description": "Exporter for the EAT format (.eat). Don't forget to eat :)",
    "warning": "",
    "wiki_url": "http://www.trollgames.no/"\
        "Scripts/File_I-O/EAT_Exporter",
    "category": "Import/Export"} 

# ---------------------------------
# --------- HELPER FUNCS ----------
# ---------------------------------

def write_float(file, f):
    file.write(struct.pack("<f", f))
    
def write_string(file, s):
    file.write(bytes(s.encode('utf-8')))
    write_byte(file,0)   
        
def write_byte(file, data):
    file.write(struct.pack("<B", data))
    
def write_uint(file, data):
    file.write(struct.pack("<L", data))

def write_ushort(file, data):
    file.write(struct.pack("<H", data))

def write_matrix(file, m):
    data = [m[0][0], m[0][1], m[0][2], m[0][3], m[1][0], m[1][1], m[1][2], m[1][3], m[2][0], m[2][1], m[2][2], m[2][3], m[3][0], m[3][1], m[3][2], m[3][3]]
    file.write(struct.pack("<ffffffffffffffff", *data))
      
def WriteTriangle(file, v0, v1, v2):
    WriteVertex(file, v0)
    WriteVertex(file, v1)
    WriteVertex(file, v2)

def WriteVertex(file, co):
    write_float(file, co.x)
    write_float(file, co.y)
    write_float(file, co.z)

def WriteNormal(file, n0, n1, n2):
    if (optimize == 1):
        xnormal = (n0.x + n1.x + n2.x) / 3
        ynormal = (n0.y + n1.y + n2.y) / 3
        znormal = (n0.z + n1.z + n2.z) / 3
        
        write_float(file, xnormal)
        write_float(file, ynormal)
        write_float(file, znormal)

# --------------------------------

def WriteHeader(file):
    if (debug == 1):
        print("header..")
    
    write_string(file, 'eat')
    
    numObjs = len(bpy.data.objects)
    
    write_uint(file, numObjs)

def WriteMeshColors(file, mesh):
    # a note on vertex_colors:
    # a mesh can have zero, one or more vertexcolors
    # each index into mesh.vertex_colors[idx] corresponds to a texture layer (?)
    # http://blenderartists.org/forum/archive/index.php/t-199308.html
    # mesh.vertex_colors[0].data.color1 to color4 (up to 4 verts in a face?)

    if (debug == 1):
        print ('checking mesh %s for colors...' % (mesh.name))

    if mesh.vertex_colors:
        layerCount = len(mesh.vertex_colors)
        colorCount = len(mesh.vertex_colors[0].data)
        if (debug == 1):
            print ('Mesh has %i colors in layer 0 and %i layers' % (colorCount, layerCount))           

        write_uint(file,colorCount)
        for col in mesh.vertex_colors[0].data:
            red = (col.color1.r + col.color2.r + col.color3.r) / 3.0
            green = (col.color1.g + col.color2.g + col.color3.g) / 3.0
            blue = (col.color1.b + col.color2.b + col.color3.b) / 3.0
            # color4 is alpha? or face 4?
            write_float(file, red)
            write_float(file, green)
            write_float(file, blue)
    else:
        if (debug == 1):
            print ('Mesh doesnt have any vertex_colors')
        write_uint(file,0)
        

def WriteMeshes(file):
    id = 0
    for obj in bpy.data.objects:
        id += 1
        write_uint(file, id)
        
        if (debug == 1):
            print ('Saving object ID:%i, %s' % (id, obj.name))
        
        write_string(file, obj.name)
        write_matrix(file, obj.matrix_world * obj.matrix_local)

        # Type (Mesh, spawnpoint, enemy etc.)
        write_string(file, obj.type)
        
        if obj.name in bpy.data.meshes:
            mesh = bpy.data.meshes[obj.name]
            # this is a mesh
            write_uint(file, 1)

            facecount = 0
            
            for faces in mesh.faces:
                if (len(faces.vertices) == 3):
                    facecount += 1
                if (len(faces.vertices) == 4):
                    facecount += 2
            
            if (debug == 1):
                print ("uint: %i (tells cpp importer how many faces to read, if 0 there is no mesh)" % facecount)

            write_uint(file, facecount)
            
            if (debug == 1):
                print ('Mesh: %s Faces: %i' % (mesh.name, facecount))

            if (facecount > 0):
                WriteMeshColors(file, mesh)
            else:
                if (debug == 1):
                    print ('Mesh doesnt have faces, so no colors either')
                write_uint(file,0)
                
            # Get faces & Normals
            for faces in mesh.faces:
                v0 = mesh.vertices[faces.vertices[0]]
                v1 = mesh.vertices[faces.vertices[1]]
                v2 = mesh.vertices[faces.vertices[2]]
                WriteNormal(file, v0.normal, v1.normal, v2.normal)
                WriteTriangle(file, v0.co, v1.co, v2.co)
                
                if (len(faces.vertices) == 4):
                    v3 = mesh.vertices[faces.vertices[3]]
                    WriteNormal(file, v0.normal, v2.normal, v3.normal)
                    WriteTriangle(file, v0.co, v2.co, v3.co)

        else:
            if (debug == 1):
                print ("uint = 0 (No mesh! this integer tells cpp importer how many faces to read)")
            write_uint(file, 0)
                    
               
# --------------------------------

from bpy.props import *

# DO IT
class EatExporter(bpy.types.Operator):
    """Export to the EAT 3D format (.eat)"""

    bl_idname = "export.eat"
    bl_label = "Export EAT"

    filepath = StringProperty()
    optimize = BoolProperty(name="Optimize", description="Include normals and other optimizations.", default=True)
    debug    = BoolProperty(name="Print Debug", description="Print debug information.", default=True)
    
    def execute(self, context):
        file = open(self.filepath, "wb")
        
        WriteHeader(file)
        WriteMeshes(file)
    
        file.close()

        #self.report( "INFO", "BOOM!  file exported succesfully " + self.filepath )
        
        return {"FINISHED"}

    def invoke(self, context, event):
        WindowManager = context.window_manager
        WindowManager.fileselect_add(self)
        return {"RUNNING_MODAL"}
    
def menu_func(self, context):
    filepath = os.path.splitext(bpy.data.filepath)[0]+".eat"
    self.layout.operator(EatExporter.bl_idname, text="Eat (.eat)").filepath = filepath

def register():
    bpy.types.INFO_MT_file_export.append(menu_func)

def unregister():
    bpy.types.INFO_MT_file_export.remove(menu_func)

if __name__ == "__main__":
    register()

## rooms
# x id
# x name
# x vets
# x normals
# - texID
# - texPath
# - uvs
# - bbox
# - spawningpoint
# - doors

# lamps

# . size
# . name
# . uv?
# uv
# doors

## tools
# Door selector
#
